﻿using System.Windows.Controls;
using System.Windows.Input;
using WickedFlame.Core;
using System.Windows;
using System.Windows.Media;

namespace WickedFlame.Core
{
	/// <summary>
	/// Decorator that sends mouse and key events to the selected canvas
	/// </summary>
	public class CanvasEventProvider : Decorator
	{
		public DrawingCanvas Canvas
		{
			get
			{
				return (DrawingCanvas)GetValue(CanvasProperty);
			}
			set
			{
				SetValue(CanvasProperty, value);
			}
		}

		public static readonly DependencyProperty CanvasProperty =
			DependencyProperty.Register("Canvas", typeof(DrawingCanvas), typeof(CanvasEventProvider));

		protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
		{
			base.OnPreviewMouseLeftButtonDown(e);

			this.Focus();

			if (Canvas == null)
				return;

			if (Canvas != null && Canvas.SelectedLayer != null && DrawingCanvas.ToolsControler.SelectedTool != null && Canvas.SelectedLayer.IsSelecteable && Canvas.SelectedLayer.Visibility == Visibility.Visible)
				DrawingCanvas.ToolsControler.SelectedTool.OnMouseLeftButtonDown(Canvas, e);
		}

		protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
		{
			base.OnMouseLeftButtonUp(e);

			if (Canvas == null || !IsCanvasFocused)
				return;

			if (Canvas != null && Canvas.SelectedLayer != null && DrawingCanvas.ToolsControler.SelectedTool != null && Canvas.SelectedLayer.IsSelecteable && Canvas.SelectedLayer.Visibility == Visibility.Visible)
				DrawingCanvas.ToolsControler.SelectedTool.OnMouseLeftButtonUp(Canvas, e);
		}

		protected override void OnMouseRightButtonUp(MouseButtonEventArgs e)
		{
			base.OnMouseRightButtonUp(e);

			if (Canvas == null || !IsCanvasFocused)
				return;

			if (Canvas != null && Canvas.SelectedLayer != null && DrawingCanvas.ToolsControler.SelectedTool != null && Canvas.SelectedLayer.IsSelecteable && Canvas.SelectedLayer.Visibility == Visibility.Visible)
				DrawingCanvas.ToolsControler.SelectedTool.OnMouseRightButtonUp(Canvas, e);
		}

		protected override void OnMouseMove(MouseEventArgs e)
		{
			base.OnMouseMove(e);

			if (Canvas == null || !IsCanvasFocused)
				return;

			if (Canvas != null && Canvas.SelectedLayer != null && DrawingCanvas.ToolsControler.SelectedTool != null && Canvas.SelectedLayer.IsSelecteable && Canvas.SelectedLayer.Visibility == Visibility.Visible)
				DrawingCanvas.ToolsControler.SelectedTool.OnMouseMove(Canvas, e);
		}

		protected override void OnPreviewKeyDown(KeyEventArgs e)
		{
			base.OnPreviewKeyDown(e);

			if (Canvas == null || !IsCanvasFocused)
				return;

			if (Canvas != null && Canvas.SelectedLayer != null && DrawingCanvas.ToolsControler.SelectedTool != null && Canvas.SelectedLayer.IsSelecteable && Canvas.SelectedLayer.Visibility == Visibility.Visible)
				DrawingCanvas.ToolsControler.SelectedTool.OnKeyDown(Canvas, e);
		}

		protected override void OnPreviewTextInput(TextCompositionEventArgs e)
		{
			base.OnPreviewTextInput(e);

			if (Canvas == null || !IsCanvasFocused)
				return;

			if (Canvas != null && Canvas.SelectedLayer != null && DrawingCanvas.ToolsControler.SelectedTool != null && Canvas.SelectedLayer.IsSelecteable && Canvas.SelectedLayer.Visibility == Visibility.Visible)
				DrawingCanvas.ToolsControler.SelectedTool.OnTextInput(Canvas, e);
		}

		private bool IsCanvasFocused
		{
			get
			{
				var wnd = Application.Current.MainWindow;
				FocusManager.SetIsFocusScope(wnd, true);
				UIElement focusedElement = FocusManager.GetFocusedElement(wnd) as UIElement;

				return FindChild<DrawingCanvas>(focusedElement) != null;
			}
		}

		//public static T FindVisualParent<T>(UIElement element) where T : UIElement
		//{
		//    UIElement parent = element; while (parent != null)
		//    {
		//        T correctlyTyped = parent as T; if (correctlyTyped != null)
		//        {
		//            return correctlyTyped;
		//        }
		//        parent = VisualTreeHelper.GetParent(parent) as UIElement;
		//    } return null;
		//}

		public static T FindChild<T>(DependencyObject parent) where T : DependencyObject
		{
			if (parent == null) return null;

			T childElement = null; int childrenCount = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < childrenCount; i++)
			{
				var child = VisualTreeHelper.GetChild(parent, i);
				T childType = child as T; if (childType == null)
				{
					childElement = FindChild<T>(child); if (childElement != null) break;
				}
				else
				{
					childElement = (T)child; break;
				}
			} return childElement;
		}
	}
}
